#include "std.h"
#include "http.h"

char *web_root = "www";

// http_write_chunk(fw, "hello", 5)
// 共发送 3+5+2 个字符
// 5\r\nHELLO\r\n
void http_write_chunk(FILE *fw, void *chunk, int size)
{
    fprintf(fw, "%x\r\n", size);
    fwrite(chunk, size, 1, fw);
    fprintf(fw, "\r\n");
}

// 共发送 3+0+2 个字符
// 0\r\n\r\n
void http_end(FILE *fw)
{
    http_write_chunk(fw, NULL, 0);
    fflush(fw);
}

void http_prints(FILE *fw, void *string)
{
    int size = strlen(string);
    http_write_chunk(fw, string, size);
}

void http_printf(FILE *fw, const char *format, ...)
{
    va_list ap;
    va_start(ap, format);
    char chunk[100];
    int size = vsprintf(chunk, format, ap);
    va_end(ap);

    http_write_chunk(fw, chunk, size);
}

void write_file(FILE *fw, char *path)
{
	FILE *file = fopen(path, "r");
	char line[256];

	while (fgets(line, sizeof(line), file)) {
		http_prints(fw, line);
	}
	fclose(file);
}

void write_dir(FILE *fw, char *path, char *parent)
{
	char new_path[256];
	//puts(parent);
	bzero(new_path, sizeof(new_path));
	strcpy(new_path, web_root);
	strcat(new_path, path);
	//puts(new_path);

	DIR *dir = opendir(new_path);
	struct dirent *entry;
	
	http_prints(fw, "<html>");
	http_printf(fw, "%s%s%s", "<head><title>Index of ", path, "</title></head>");
	http_prints(fw, "<body>");
	http_printf(fw, "%s%s%s", "<h1>Index of ", path, "</h1>");
	http_prints(fw, "<hr>");
	http_printf(fw, "%s%s%s", "<a href=\"", parent, "\">Parent dir</a><br>");

	while (entry = readdir(dir)) {
		//puts(entry->d_name);
		if (strcmp(entry->d_name, ".") == 0)
			continue;

		if (strcmp(entry->d_name, "..") == 0)
			continue;

		http_printf(fw, "%s%s%s%s%s%s%s", "<a href=\"", path, "/", entry->d_name, "\">", entry->d_name, "</a><br>");
	}
	http_prints(fw, "<hr>");
	http_prints(fw, "</body>");
	http_prints(fw, "</html>");

	closedir(dir);
}

void http_send_headers(FILE *fp, char *content_type)
{
    fprintf(fp, "HTTP/1.1 200 OK\r\n");
    fprintf(fp, "Server: tiny httpd\r\n");
    fprintf(fp, "Content-type: %s\r\n", content_type);
    fprintf(fp, "Transfer-Encoding: chunked\r\n");
    fprintf(fp, "\r\n");
}

// GET /index.html HTTP/1.1\r\n
char *http_parse_req(FILE *fr, char *req, int req_size)
{
    fgets(req, req_size, fr); 
    puts(req);
    char begin[10], end[15];
    char *mid = malloc(sizeof(char) * 256);
    sscanf(req, "%s %s %s", begin, mid, end);
    return mid;
}

void http_handler(int fd)
{
    FILE *fr = fdopen(fd, "r");
    FILE *fw = fdopen(fd, "w");

    char req[1024];
    char *path;
    char http_path[256];
    char parent[256];
    bzero(parent, sizeof(parent));
    bzero(http_path, sizeof(http_path));
    path = http_parse_req(fr, req, sizeof(req));
    strcpy(http_path, path);
    if (strcmp(http_path, "/") == 0)
	    strcat(http_path, "index.html");

    char *ptr = strrchr(path, '/');
    int len = ptr - path;
    if (len == 0)
	    strcpy(parent, "/");
    else
	    strncpy(parent, path, len);

    char new_path[1024];
    bzero(new_path, sizeof(new_path));
    strcpy(new_path, web_root);
    strcat(new_path, http_path);

    struct stat info;
    stat(new_path, &info);

    if (S_ISDIR(info.st_mode)) {
	    http_send_headers(fw, "text/html");
	    write_dir(fw, http_path, parent);
    }
    else {
	    if (strstr(new_path, ".html"))
		    http_send_headers(fw, "text/html");
	    else
		    http_send_headers(fw, "text/plain");
	    write_file(fw, new_path);
    }
    //http_prints(fw, "<h1>HELLO</h1>");
    http_end(fw);
}
